package com.ruoyi.file.controller;

import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.file.config.ResourcesConfig;
import com.ruoyi.file.service.IMinioSysFileService;
import com.ruoyi.file.utils.UploadData;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.*;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.IOUtils;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.file.FileUtils;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

/**
 * 文件请求处理
 * 
 * @author ruoyi
 */
@RestController
public class SysFileController {
    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);

    @Autowired
    private IMinioSysFileService minioSysFileService;

    @Autowired
    private RemoteUserService remoteUserService;

    private static String getFileSuffixName(String fileName) {
        String suffixName = null;
        if (!StringUtils.isEmpty(fileName)) {
            suffixName = fileName.substring(fileName.lastIndexOf(".") + 1);
        }
        return suffixName;
    }

    /**
     * 文件上传请求
     */
    @PostMapping("upload")
    public R<SysFile> upload(MultipartFile file, UploadData uploadData) {
        try {
            if (("pic".equals(uploadData.getCol()) || "vid".equals(uploadData.getCol()) || "fj".equals(uploadData.getCol())) &&
                ("shop".equals(uploadData.getTable()) || "product".equals(uploadData.getTable()) || "banner".equals(uploadData.getTable()) ||
                "teacher".equals(uploadData.getTable()) || "course".equals(uploadData.getTable()) ||
                "material".equals(uploadData.getTable()))) {
                SysDept sysDept;
                ShProductPicture shProductPicture;
                ShBannerPicture shBannerPicture;
                // 上传并返回访问地址
                String url = "";
                String fileKzm = "";
                if ("material".equals(uploadData.getTable())) {
                    R<MaterialInfo> rtn = this.remoteUserService.getMaterialZl(Long.valueOf(uploadData.getId()));
                    if (null!=rtn) {
                        fileKzm = getFileSuffixName(file.getOriginalFilename());
                        MaterialInfo info = rtn.getData();
                        String fileNameV = (null == info.getAge() ? "" : info.getAge()) +
                                (null == info.getGradeName() ? "" : info.getGradeName()) +
                                (null == info.getSemesterName() ? "" : info.getSemesterName()) +
                                info.getMaterialName();
                        String fileName = fileNameV +"."+fileKzm;
                        if ("pdf".equalsIgnoreCase(fileKzm)) {
                            url = minioSysFileService.uploadFileV(file, fileNameV);
                        }else {
                            url = minioSysFileService.uploadFileU(file, fileName);
                        }
                    }
                }else {
                    R<MaterialInfo> rtn = this.remoteUserService.getMaterialZlsize(file.getSize());
                    if (null!=rtn&&null!=rtn.getData()) {
                        return R.fail("资料已存在，上传失败");
                    }else {
                        url = minioSysFileService.uploadFile(file);
                    }
                }
                SysFile sysFile = new SysFile();
                sysFile.setName(FileUtils.getName(url));
                sysFile.setUrl(url);
                switch (uploadData.getTable()) {
                    case "shop":
                        sysDept = new SysDept();
                        sysDept.setDeptId(Long.valueOf(uploadData.getId()));
                        sysDept.setShopLogo(url);
                        this.remoteUserService.updateDeptPic(sysDept);
                        break;
                    case "banner":
                        shBannerPicture = new ShBannerPicture();
                        shBannerPicture.setBannerId(Long.valueOf(uploadData.getId()));
                        shBannerPicture.setProductPic(url);
                        shBannerPicture.setIsVideo(0);
                        shBannerPicture.setCreateTime(DateUtils.getNowDate());
                        this.remoteUserService.addBannerPic(shBannerPicture);
                        break;
                    case "product":
                        shProductPicture = new ShProductPicture();
                        shProductPicture.setProductId(Long.valueOf(uploadData.getId()));
                        if ("pic".equals(uploadData.getCol())) {
                            shProductPicture.setProductPic(url);
                            shProductPicture.setIsVideo(0);
                        } else if ("vid".equals(uploadData.getCol())) {
                            shProductPicture.setProductPic(url);
                            shProductPicture.setIsVideo(1);
                            R<ShProductPicture> rtn = this.remoteUserService.getProductPic(Long.valueOf(uploadData.getId()));
                            if (null==rtn.getData()) {
                                ShProductPicture shProductPicturePic = new ShProductPicture();
                                shProductPicturePic.setProductId(Long.valueOf(uploadData.getId()));
                                LocalDate date = LocalDate.now();
                                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                                String filePath = ResourcesConfig.getLocalFilePath() + "/" + formatter.format(date) + "/" + shProductPicture.getProductId() + "p.jpg";
                                this.fetchFrame(url, filePath);
                                File fileCover = new File(filePath);
                                String urlCover = minioSysFileService.uploadFile(getMultipartFile(fileCover));
                                shProductPicturePic.setProductPic(urlCover);
                                shProductPicturePic.setIsVideo(0);
                                shProductPicturePic.setCreateTime(DateUtils.getNowDate());
                                this.remoteUserService.addPicturePic(shProductPicturePic);
                                fileCover.delete();
                            }
                        }
                        shProductPicture.setCreateTime(DateUtils.getNowDate());
                        this.remoteUserService.addPicturePic(shProductPicture);
                        break;
                    case "teacher":
                        ShCourseTeacher shCourseTeacher = new ShCourseTeacher();
                        shCourseTeacher.setId(Long.valueOf(uploadData.getId()));
                        shCourseTeacher.setTeacherHeadimgurl(url);
                        this.remoteUserService.editTeacherPic(shCourseTeacher);
                        break;
                    case "course":
                        ShCourse shCourse = new ShCourse();
                        shCourse.setId(Long.valueOf(uploadData.getId()));
                        if ("pic".equals(uploadData.getCol())) {
                            shCourse.setVideoCover(url);
                        } else if ("vid".equals(uploadData.getCol())) {
                            shCourse.setVideoUrl(url);
                            LocalDate date = LocalDate.now();
                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                            String filePath = ResourcesConfig.getLocalFilePath() + "/" + formatter.format(date) + "/" + shCourse.getId() + ".jpg";
                            this.fetchFrame(url, filePath);
                            File fileCover = new File(filePath);
                            String urlCover = minioSysFileService.uploadFile(getMultipartFile(fileCover));
                            shCourse.setVideoCover(urlCover);
                            fileCover.delete();
                        }
                        this.remoteUserService.editCoursePic(shCourse);
                        break;
                    case "material":
                        MaterialInfo materialInfo = new MaterialInfo();
                        materialInfo.setId(Long.valueOf(uploadData.getId()));
                        materialInfo.setUrl(url);
                        materialInfo.setMaterialSize(file.getSize());
                        this.remoteUserService.editMaterialZl(materialInfo);
                        break;
                }
                return R.ok(sysFile);
            }
            return R.fail("");
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        }
    }

    @PostMapping("downfile")
    public R<String> downfile(@RequestParam("url") String url, @RequestParam("filePath") String filePath) {
        try {
            minioSysFileService.downFile(url, filePath);
            return R.ok("下载成功");
        }catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }

    /**
     * 捕捉图片第一帧
     *
     * @throws Exception
     */
    private static void fetchFrame(String videoUrl, String imgUrl) throws Exception {
        FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(videoUrl);
        Java2DFrameConverter converter = new Java2DFrameConverter();
        frameGrabber.start();
        //解码长度
        int length = frameGrabber.getLengthInFrames();
        //时间
        int i = 0;
        Frame frame = null;
        while (i < length) {
            //过滤前五帧，避免出现全黑的图片
            frame = frameGrabber.grabFrame();
            if (i > 10 && (frame.image != null)) {
                break;
            }
            i++;
        }
        // Frame frame = frameGrabber.grabFrame();
        BufferedImage bufferedImage = converter.convert(frame);
        //照片保存文件夹
        File targetFile = new File(imgUrl);
        //文件夹不存在就新建
        if (!targetFile.isDirectory()) {
            targetFile.mkdirs();
        }
        //写入文件夹,以jpg图片格式
        ImageIO.write(bufferedImage, "jpg", targetFile);
        //停止转化为帧
        frameGrabber.stop();
    }

    private static MultipartFile getMultipartFile(File file) {
        FileItem item = new DiskFileItemFactory().createItem("file"
                , MediaType.MULTIPART_FORM_DATA_VALUE
                , true
                , file.getName());
        try (InputStream input = new FileInputStream(file);
             OutputStream os = item.getOutputStream()) {
            // 流转移
            IOUtils.copy(input, os);
        } catch (Exception e) {
            throw new IllegalArgumentException("Invalid file: " + e, e);
        }
        return new CommonsMultipartFile(item);
    }

    /**
     * 通用上传删除请求
     */
    @PostMapping("delete")
    public R<String> uploadFiledelete(@RequestBody UploadData uploadData) {
        try {
            SysDept sysDept;
            ShCourseTeacher shCourseTeacher;
            if (null != uploadData.getUrl() && uploadData.getUrl().indexOf("aliyuncs.com/") > 0) {
                String[] keyAry = uploadData.getUrl().split("aliyuncs.com/");
                minioSysFileService.deleteFile(keyAry[1]);
            }
            switch (uploadData.getTable()) {
                case "shop":
                    sysDept = new SysDept();
                    sysDept.setDeptId(Long.valueOf(uploadData.getId()));
                    sysDept.setShopLogo("");
                    this.remoteUserService.updateDeptPic(sysDept);
                    break;
                case "banner":
                    this.remoteUserService.delBannerPic(Long.valueOf(uploadData.getYwId()));
                    break;
                case "product":
                    this.remoteUserService.delPicturePic(Long.valueOf(uploadData.getYwId()));
                    break;
                case "teacher":
                    shCourseTeacher = new ShCourseTeacher();
                    shCourseTeacher.setId(Long.valueOf(uploadData.getId()));
                    shCourseTeacher.setTeacherHeadimgurl("");
                    this.remoteUserService.editTeacherPic(shCourseTeacher);
                    break;
                case "course":
                    ShCourse shCourse = new ShCourse();
                    shCourse.setId(Long.valueOf(uploadData.getId()));
                    shCourse.setVideoCover("");
                    this.remoteUserService.editCoursePic(shCourse);
                    break;
                case "material":
                    MaterialInfo materialInfo = new MaterialInfo();
                    materialInfo.setId(Long.valueOf(uploadData.getId()));
                    materialInfo.setUrl("");
                    materialInfo.setMaterialSize(null);
                    this.remoteUserService.editMaterialZl(materialInfo);
                    break;
            }
            return R.ok("");
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }

    @PostMapping("del/{filekey}")
    public R<String> del(@PathVariable("filekey") String filekey) {
        try {
            minioSysFileService.deleteFile(filekey);
            return R.ok("");
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }
}